package com.kly.order.serviceImpl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import com.fqgj.common.api.Response;
import com.fqgj.common.utils.CollectionUtils;
import com.kly.dto.*;
import com.kly.enums.ProductCategory;
import com.kly.enums.TradeResultStatus;
import com.kly.order.ServiceUtils;
import com.kly.order.db.dao.ConsumptionRecordDao;
import com.kly.order.db.dao.MemberBenefitsDao;
import com.kly.order.db.dao.MemberDao;
import com.kly.order.db.dao.ProductBenefitsDao;
import com.kly.order.db.dbo.UserPCountDBO;
import com.kly.order.db.entity.ConsumptionRecordEntity;
import com.kly.order.db.entity.MemberBenefitsEntity;
import com.kly.order.db.entity.ProductBenefitsEntity;
import com.kly.order.mapper.MemberBenefitsMapper;
import com.kly.order.mapper.ProductMapper;
import com.kly.service.MemberBenefitsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service("memberBenefitsService")
public class MemberBenefitsServiceImpl implements MemberBenefitsService {
    @Resource
    MemberBenefitsDao memberBenefitsDao;
    @Resource
    private ProductBenefitsDao productBenefitsDao;
    @Resource
    MemberBenefitsMapper mapper;
    @Resource
    ProductMapper productMapper;
    @Resource
    ConsumptionRecordDao consumptionRecordDao;
    @Resource
    MemberDao memberDao;

    /**
     * 获取会员服务集合
     *
     * @param memberCode  会员号
     * @param benefitCode 服务code，为空则查询会员全部服务
     * @return 会员服务集合
     */
    @Override
    public Response<List<MemberBenefitsDto>> getMemberBenefits(String memberCode, Integer benefitCode) {
        Map<String, Object> map = new HashMap<>();
        map.put("memberCode", memberCode);
        map.put("benefitCode", benefitCode);
        map.put("date", new Date());
        List<MemberBenefitsEntity> memberBenefitsEntities = memberBenefitsDao.findAvailableServices(map);

        if (memberBenefitsEntities == null || memberBenefitsEntities.isEmpty()) {
            return Response.error(TradeResultStatus.NO_MEMBER_BENEFITS);
        }

        List<MemberBenefitsDto> benefitsDtoList = memberBenefitsEntities.stream().map(mapper::toDto).collect(Collectors.toList());

        return Response.ok(benefitsDtoList);

    }


    /**
     * 解析ProductConfig中的benefits数据。
     * 检查是否存在与memberCode匹配的MemberBenefits记录，如果不存在，则新增记录。
     * 遍历benefits，获取每个Benefit。
     * 根据member.getExpiryDate() - member.getEffectiveDate()获取天数，然后用这个天数除以Benefit.days，如果不能整除则结果+1，得到结果X。
     * 循环X次，每次将一个新的MemberBenefit添加到MemberBenefitList中。
     * 设置新MemberBenefit的effectiveDate为Member.effectiveDate，expiryDate为Member.effectiveDate + Benefit.days，maxUses为Benefit.maxSize。
     * 每个新的 MemberBenefitsEntity 的开始时间应该是上一条记录的结束时间。
     *
     * @param member  会员
     * @param product 产品
     */
    @Override
    public Response<String> saveMemberBenefits(MemberDto member, ProductDto product) {
        Map<String, Object> params = ServiceUtils.getParams();
        params.put("memberCode", member.getMemberCode());
        // 查找最新的MemberBenefits记录
        List<MemberBenefitsEntity> memberBenefitsList = memberBenefitsDao.findLatestExpiryDatesByMemberCode(params);
        Map<Integer, MemberBenefitsEntity> memberBenefitsMap = toBenefitCodeMap(memberBenefitsList);

        params = ServiceUtils.getParams();
        params.put("productCategory", product.getProductCategory());
        params.put("appCode", product.getAppCode());
        params.put("isLimited", 1);
        List<ProductBenefitsEntity> productBenefits = productBenefitsDao.selectByProductCategory(params);
        List<Benefit> benefits = new ArrayList<>();
        for (ProductBenefitsEntity productBenefit : productBenefits) {
            Benefit benefit = productMapper.toBenefit(productBenefit);
            benefits.add(benefit);
        }

        // 循环处理每个benefit
        for (Benefit benefit : benefits) {
            List<MemberBenefitsEntity> MemberBenefitList = new ArrayList<>();

            // 计算member的有效期天数
            long membershipDays = DateUtil.betweenDay(member.getEffectiveDate(), member.getExpiryDate(), true);

            // 计算需要添加的记录次数
            long recordCount = membershipDays / benefit.getDays();
            if (membershipDays % benefit.getDays() != 0) {
                recordCount++;
            }
            //获取最新的MemberBenefits记录
            MemberBenefitsEntity latestMemberBenefit = memberBenefitsMap.get(benefit.getBenefitCode());

            // 判断最新记录的过期时间是否大于当前时间
            Date currentStartDate;
            if (latestMemberBenefit != null && DateUtil.compare(latestMemberBenefit.getExpiryDate(), new Date()) > 0) {
                // 如果大于当前时间，那么将latestMemberBenefit的过期时间作为开始时间
                currentStartDate = latestMemberBenefit.getExpiryDate();

                // 重新计算需要添加的记录次数
                long remainingDays = DateUtil.betweenDay(currentStartDate, member.getExpiryDate(), true);
                recordCount = remainingDays / benefit.getDays();
                if (remainingDays % benefit.getDays() != 0) {
                    recordCount++;
                }
            } else {
                // 如果小于等于当前时间，那么将Member的开始时间作为开始时间
                currentStartDate = member.getEffectiveDate();
            }

            // 循环添加记录
            for (int i = 0; i < recordCount; i++) {
                MemberBenefitsEntity memberBenefit = new MemberBenefitsEntity();

                // 设置各项属性
                memberBenefit.setUserCode(member.getUserCode());
                memberBenefit.setMemberCode(member.getMemberCode());
                memberBenefit.setBenefitCode(benefit.getBenefitCode());
                memberBenefit.setBenefitName(benefit.getBenefitName());
                memberBenefit.setEffectiveDate(currentStartDate);
                memberBenefit.setExpiryDate(DateUtil.offsetDay(currentStartDate, benefit.getDays()));
                memberBenefit.setMaxUses(benefit.getMaxSize());
                memberBenefit.setStatus(1); // Assume status 1 means active

                // 下一条记录的开始时间就是这一条的结束时间
                currentStartDate = memberBenefit.getExpiryDate();

                MemberBenefitList.add(memberBenefit);
            }
            if (CollUtil.isNotEmpty(MemberBenefitList)){
                memberBenefitsDao.batchInsert(MemberBenefitList);
            }
            MemberBenefitList.clear();

        }
        return Response.ok();
    }

    /**
     * list集合转Map
     *
     * @param memberBenefitsEntityList 按会员代码和权益代码查找的最新会员权益集合
     * @return 最新会员权益Map
     */
    private Map<Integer, MemberBenefitsEntity> toBenefitCodeMap(List<MemberBenefitsEntity> memberBenefitsEntityList) {
        Map<Integer, MemberBenefitsEntity> benefitCodeMap = new HashMap<>();
        for (MemberBenefitsEntity memberBenefits : memberBenefitsEntityList) {
            benefitCodeMap.put(memberBenefits.getBenefitCode(), memberBenefits);
        }
        return benefitCodeMap;
    }

    /**
     * 更新会员权益使用次数
     *
     * @param reduceBenefits 权益扣减Dto
     * @return 扣减结果
     */
    @Override
    public Response<String> reduceMemberBenefits(ReduceBenefitsDto reduceBenefits) {
        Map<String, Object> params = ServiceUtils.getParams();
        params.put("userCode", reduceBenefits.getUserCode());
        params.put("benefitCode", reduceBenefits.getBenefitCode());
        params.put("date", new Date());
        List<MemberBenefitsEntity> memberBenefitsList = memberBenefitsDao.selectByMemberCodeAndTimesUsed(params);

        if (CollUtil.isEmpty(memberBenefitsList)) {

//            Map<String, Object> map = new HashMap<>();
//            map.put("userCode", reduceBenefits.getUserCode());
//            map.put("deleted", 0);
//            map.put("date", new Date());
//            Integer result = memberDao.ifMember(map);
//            log.info("reduceMemberBenefits, result:{}", result > 0);
//            if (result > 0) {
//                return Response.error(TradeResultStatus.NO_MEMBER);
//            }
            return Response.error(TradeResultStatus.NO_MEMBER_BENEFITS);

        }

        // 增加会员有效期校验
//        final Boolean isMember = memberDao.ifMember(reduceBenefits.getUserCode());
//        if (!isMember) {
//            return Response.error(TradeResultStatus.NO_MEMBER);
//        }

        MemberBenefitsEntity memberBenefits = memberBenefitsList.get(0);
        memberBenefits.setTimesUsed(memberBenefits.getTimesUsed() + 1);
        memberBenefitsDao.updateByPrimaryKey(memberBenefits);
        return Response.ok();
    }

    @Override
    public Response<List<UserPCountDto>> getUserPCount(String chatUserCode, String chatterUserCode, LocalDateTime startTime, LocalDateTime endTime) {
        List<UserPCountDBO> userPCountDBOS = consumptionRecordDao.getUserPCount(chatUserCode, chatterUserCode, startTime, endTime);
        return Response.ok(UserPCountDBO.toDto(userPCountDBOS));
    }

    @Override
    public Response<List<UserBenefitsDto>> listBenefits(String userCode, String chatUserCode) {
        final List<ConsumptionRecordEntity> consumptionRecordEntities = consumptionRecordDao.listBenefits(userCode, chatUserCode);
        if (CollectionUtils.isEmpty(consumptionRecordEntities)) {
            return Response.ok();
        }
        final List<UserBenefitsDto> userBenefitsDtos = consumptionRecordEntities.parallelStream().map(MemberBenefitsServiceImpl::toDto).collect(Collectors.toList());
        return Response.ok(userBenefitsDtos);
    }

    public static UserBenefitsDto toDto(ConsumptionRecordEntity entity) {
        UserBenefitsDto dto = new UserBenefitsDto();
        dto.setCreateDt(entity.getGmtCreate());
        BeanUtils.copyProperties(entity, dto);
        return dto;
    }

    @Override
    public Response<Integer> getUserBenefitsCount(String userCode, Integer benefitCode) {
        return Response.ok(memberBenefitsDao.selectFlashChatNum(userCode, benefitCode));
    }

    /**
     * 获取用户会员权益（包括已已过期会员但未消费的权益记录), 非会员返回为空
     */
    @Override
    public Response<List<MemberBenefitsDto>> getMemberBenefits(String userCode){

        List<MemberBenefitsEntity> memberBenefitsEntities = memberBenefitsDao.findAllBenefit(userCode);
        if (memberBenefitsEntities == null || memberBenefitsEntities.isEmpty()) {
            return Response.ok();
        }

        List<MemberBenefitsDto> benefitsDtoList = memberBenefitsEntities.stream().map(mapper::toDto).collect(Collectors.toList());

        return Response.ok(benefitsDtoList);

    }
}
